package roborally.program;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import roborally.program.command.Command;
import roborally.program.command.Condition;
import roborally.program.text.TextCommandPattern;
import roborally.program.text.TextFactory;

public class CommandManager {

	private final Set<TextCommandPattern> patterns = new HashSet<TextCommandPattern>();
	private final String EMPTY_PATTERN = "[\\s]*";
	
	private static final CommandManager commandManager = new CommandManager();
	private static final String SUB_BLOCK = "(\\()(\\s*)(\\()(.*)(\\))(\\s*)(\\))";
	
	private CommandManager() {
		for(TextFactory factory : TextFactory.values())
			patterns.add(factory.getPattern());
	}
	
	public static CommandManager get() {
		return commandManager;
	}
	
	public List<Command> create(String word) throws IllegalArgumentException {
		List<Command> commands = new ArrayList<Command>();
		word = removeRedundantBrackets(word);
		for(String block : getBlocks(word)) {
			if(Pattern.matches(EMPTY_PATTERN, block))
				continue;
			else if(Pattern.matches(SUB_BLOCK, block))
				commands.addAll(create(block.substring(1, block.length() - 1)));
			else
				commands.add(createCommand(block));
		}
		return commands;
	}
	
	//veranderd een sequentie van 2 of meer haakjes met lege karakters er tussen door 1 haakjesblok
	//vb : (( ( )  ) ) wordt ( ) 
	public String removeRedundantBrackets(String word) {
		String redundant = "(.*)((\\()(\\s*)){2,}+((\\))(\\s*)){2,}+(.*)";
		String replacement = "";
		return word.replaceAll(redundant, replacement);
	}

	private Command createCommand(String block) {
		for(TextCommandPattern lusPattern : patterns)
			if(lusPattern.matches(block)) {
				return lusPattern.create(block);
			}		
		throw new IllegalArgumentException();
	}
	
	//voor testen: public, anders mag gerust private.
	public List<String> getBlocks(String word) throws IllegalArgumentException {
		List<String> blocks = new ArrayList<String>();
		char[] wordChar = word.trim().toCharArray();
		int left = 0;
		int right = 0;
		String temp = new String();
		for(int i = 0; i < wordChar.length; i++) {
			if(wordChar[i] == '(')
				left++;
			else if(wordChar[i] == ')')
				right++;
			if(left > 0)
				temp = temp + wordChar[i];
			if(left == right && left != 0) {
				blocks.add(temp);
				temp = new String();
				left = 0;
				right = 0;
			}
		}
		return blocks;
	}
	
	public Condition createCondition(String word) throws IllegalArgumentException {
		return null;
		//TODO: implementeren.
	}
	
}
